/**
 * Flash Image Editor
 *
 * @copyright (c) CmsTop {@link http://www.cmstop.com}
 * @author    kakalong {@link http://yanbingbing.com}
 * @version   $Id: cmstop.imageEditor.js 10 2012-04-09 04:22:54Z emkiao@gmail.com $
 */
(function(window, undefined){
var document = window.document,
R_SPLIT = /[\s|,]+/,
INSTS = {},
SWF_URL = 'http://cmstop-open.googlecode.com/svn/latest/CmsTopImageEditor.swf',
flashVersion = (function(){
	try {
		return (window.ActiveXObject
			? (new window.ActiveXObject('ShockwaveFlash.ShockwaveFlash')).GetVariable('$version')
			: navigator.plugins['Shockwave Flash'].description).match(/\d+/g).join('.') || null;
	} catch (e) {
		return null;
	}
})();
var toElement = function() {
	var div = document.createElement('div');
	return function(html) {
		div.innerHTML = html;
		html = div.firstChild;
		div.removeChild(html);
		return html;
	};
}();
function append(elem, value) {
	elem.appendChild(value);
	return elem;
}
function each(o, fn) {
	o = o.split(R_SPLIT);
	for (var i = 0, l = o.length,t = o[0];i < l && fn.call(t, t, i) !== false; t = o[++i]){}
}
function version_test(a, b) {
	if (!a) return false;
	a = a.split('.');
	b = b.split('.');
	for (var i=0, l=b.length; i < l; i++) {
		if (a[i]==undefined || parseInt(a[i]) < parseInt(b[i])) {
			return false;
		}
		if (parseInt(a[i]) > parseInt(b[i])) {
			return true;
		}
	}
	return true;
}
function _genValue(obj, enc) {
	if (obj instanceof Object) {
		var arr = [];
		for (var k in obj) {
			obj[k] != null && arr.push(k+'='+ _genValue(obj[k], 1));
		}
		obj = arr.join('&');
	}
	return enc ? encodeURIComponent(obj) : obj;
}
function _genAttrs(obj) {
	var arr = [];
	for (var k in obj) {
		obj[k] && arr.push([k,'="',_genValue(obj[k]),'"'].join(''));
	}
	return arr.join(' ');
}
function _genParams(obj) {
	var arr = [];
	for (var k in obj) {
		obj[k] && arr.push(['<param name="', k, '" value="', _genValue(obj[k]), '" />'].join(''));
	}
	return arr.join('');
}
function createFlash(opts) {
	if (!opts.movie) {
		return false;
	}

	if (!version_test(flashVersion, '10.2')) {
		throw 'flash version not available';
		return false;
	}
	
	var div = document.createElement('div');
	opts.type = 'application/x-shockwave-flash';
	if (window.ActiveXObject) {
		var attrs = {
			classid:'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'
		};
		each('width height id', function(k) {
			opts[k] && (attrs[k] = opts[k]);
			delete opts[k];
		});
		div.innerHTML = [
			'<object ', _genAttrs(attrs), '>',
				_genParams(opts),
			'</object>'
		].join('');
	} else {
		opts.src = opts.movie;
		delete opts.movie;
		div.innerHTML = '<embed ' + _genAttrs(opts) + ' />';
	}
	return div.firstChild;
}
function callFlash(movie, functionName, argumentArray) {
	try {
		movie.CallFunction('<invoke name="' + functionName + '" returntype="javascript">' + __flash__argumentsToXML(argumentArray||[], 0) + '</invoke>');
	} catch (ex) {
		throw "Call to " + functionName + " failed";
	}
}
var overlay = null, mousewheel = function(){
	if (overlay.style.display != "block") {
		return;
	}
	var event = arguments[0] || window.event;
	if (event.preventDefault) {
		event.preventDefault();
	}
	event.returnValue = false;
	if (event.stopPropagation) {
		event.stopPropagation();
	}
	event.cancelBubble = true;
}, esc = function(){
	if ((arguments[0] || window.event).keyCode == 27) {
		for (var k in INSTS) {
			INSTS[k].trigger('close');
		}
	}
};
function showOverlay() {
	var body = document.body;
	if (!overlay) {
		overlay = toElement('<div style="position:fixed;top:0;left:0;z-index;999998;height:100%;width:100%;background-color:black;opacity:0.5;filter:Alpha(Opacity=50);"></div>');
		append(body, overlay);
		if (document.addEventListener) {
			document.addEventListener('mousewheel', mousewheel, false);
			document.addEventListener('DOMMouseScroll', mousewheel, false);
			document.addEventListener('keypress', esc, false);
		} else if (document.attachEvent) {
			document.attachEvent('onmousewheel', mousewheel);
			document.attachEvent('onkeypress', esc, false);
		}
	}
	overlay.style.display = "block";
}
function hideOverlay() {
	if (overlay) {
		overlay.style.display = "none";
	}
	// fix : return focus to html
	var input = toElement('<input style="width:1px;height:1px;position:fixed;left:-10px;top:10px;" />');
	append(document.body, input);
	input.focus();
	document.body.removeChild(input);
}
var ImageEditor = function(file, config, width, height) {
	width || (width = 750);
	height || (height = 500);
	var t = this,
	guid = 'IMGEDITOR' + (new Date()).getTime().toString(16),
	flashvars = {
		guid:guid,
		file:file,
		config:config
	}, movie = null, ival = null, events = {},
	elem = toElement('<div style="position:fixed;width:'+width+'px;height:'+height+'px;top:50%;left:50%;margin-left:-'+(width/2)+'px;margin-top:-'+(height/2)+'px;background-color:#000;z-index:999999;filter:progid:DXImageTransform.Microsoft.Shadow(color=#000, Direction=135, Strength=4);box-shadow:3px 3px 5px #000;"></div>');
	append(document.body, elem);
	showOverlay();
	t.bind = function(evt, func){
		(evt in events) || (events[evt] = []);
		events[evt].push(func);
	};
	t.bind('close', function(){
		hideOverlay();
		ival && clearInterval(ival);
		ival = null;
		delete INSTS[guid];
		// use setTimeout fix #error:SetReturnValue 
		setTimeout(function(){
			movie && elem.removeChild(movie);
			elem && document.body.removeChild(elem);
			movie = null;
			elem = null;
		}, 0);
	});
	t.trigger = function(evt, args) {
		if (evt in events) {
			for (var i=0, func; (func = events[evt][i++]) && func.apply(t, args||[]) !== false;) {
			}
		}
	};
	t.callFlash = function(functionName, argumentArray){
		callFlash(movie, functionName, argumentArray);
	};
	INSTS[guid] = t;
	function display(){
		var w = elem.offsetWidth, h = elem.offsetHeight;
		if (!w || !h) return;
		ival && clearInterval(ival);
		movie = createFlash({
			movie:SWF_URL,
			id:guid,
			width:width,
			height:height,
			flashvars:flashvars,
			quality:'high',
			wmode:'window',
			devicefont:"true",
			allowFullScreen:"true",
			allowScriptAccess:'always'
		});
		append(elem, movie);
	}
	ival = setInterval(display, 1000);
	display();
};
ImageEditor.open = function(fileName, width, height) {
	return new ImageEditor(fileName, width, height);
};
ImageEditor.trigger = function(guid, evt, args) {
	(guid in INSTS) && INSTS[guid].trigger(evt, args);
};
ImageEditor.testExternalInterface = function(guid) {
	try {
		(guid in INSTS) && INSTS[guid].callFlash('testExternalInterface');
	} catch (e) {}
};

window.ImageEditor = ImageEditor;

})(window);